package com.mrzhou.rabbit.consumer;

import com.mrzhou.common.constant.MQConstant;
import com.mrzhou.data.support.RedisService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException;

import java.io.IOException;
import java.util.Map;

/**
 * 邮件发送的消费者
 */
@Component
@Slf4j
public class EmailConsumer {

    @Autowired
    private RedisService redisService;

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = MQConstant.EMAIL_MSG_QUEUE, durable = "true"),
            arguments = {
                    @Argument(name = MQConstant.KEY_DEAD_EXCHANGE, value = MQConstant.MSG_DEAD_EXCHANGE),
                    @Argument(name = MQConstant.KEY_DEAD_ROUTINGKEY, value = MQConstant.MSG_DEAD_ROUTINGKEY),
            },
            exchange = @Exchange(value = MQConstant.EMAIL_MSG_EXCHANGE, type = "topic"),
            key = MQConstant.EMAIL_MSG_ROUTINGKEY
    ))
    public void receive(String message, Message msg, Channel channel) throws IOException {
        long deliveryTag = msg.getMessageProperties().getDeliveryTag();
        try{

            System.out.println(message);

            //第一个deliveryTag参数为每条信息带有的tag值，第二个multiple参数为布尔类型
            //为true时会将小于等于此次tag的所有消息都确认掉，如果为false则只确认当前tag的信息，可根据实际情况进行选择。
            channel.basicAck(deliveryTag, false);
        } catch (IndexOutOfBoundsException e) {
            log.error("每日调用的接口超出最大限制！");
            channel.basicNack(deliveryTag, false, false); //抛弃此消息, 消息进入死信队列, 前提是队列设置了对应的死信队列
        } catch (ResourceAccessException e) {
            log.error("网络连接失败, 将消息重新入列！");
            channel.basicNack(deliveryTag, false, true); // 消息重新入列
        }
    }


    /**
     *  未发送的邮件在一段时间后继续发送(定时发送邮件)
     *  思路: 1. 将其中的消息再次放到一个新的对列(A)并设置一个超时时间; 当消息超时后会将消息再次转到 A对列的死信路由
     *             3. 创建对列(B)接受A(对列的死信路由中的消息), 此时在重新发送邮件
     *   按以上思路即可实现定时处理消息
     */
    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = MQConstant.MSG_DEAD_QUEUE, durable = "true"),
            exchange = @Exchange(value = MQConstant.MSG_DEAD_EXCHANGE, type = "topic"),
            key = MQConstant.MSG_DEAD_ROUTINGKEY
    ))
    public void handlerDead(Map<String, Object> message, Message msg, Channel channel) throws IOException {
        Long deliveryTag = msg.getMessageProperties().getDeliveryTag(); // 获取当前的消息ID

    }

}
